﻿using Microsoft.Extensions.Caching.StackExchangeRedis;
using Microsoft.Extensions.Options;
using System;
using System.Threading;
using System.Threading.Tasks;
using Volo.Abp.DependencyInjection;
using Xms.Abp.Core;

namespace Xms.Abp.Caching;

public class CacheSerialNumberProvider : ISerialNumberProvider, ISingletonDependency
{
    public string Name => "Cache";
    protected IAbpLazyServiceProvider LazyServiceProvider { get; }
    private IXmsCache _cache;
    protected IXmsCache Cache
    {
        get
        {
            if (_cache == null)
            {
                var options = LazyServiceProvider.LazyGetRequiredService<IOptions<RedisCacheOptions>>().Value;
                _cache = RedisCacheProvider.CreateCache(LazyServiceProvider, options.Configuration);
            }
            return _cache;
        }
    }

    public CacheSerialNumberProvider(IAbpLazyServiceProvider lazyServiceProvider)
    {
        LazyServiceProvider = lazyServiceProvider;
    }

    public async Task<long> CreateAsync(string key, int quantity = 1, SerialNumberGrowthType growthType = SerialNumberGrowthType.None, CancellationToken cancellationToken = default)
    {
        var expiration = growthType switch
        {
            SerialNumberGrowthType.ByYear => new DateTime(DateTime.Today.Year + 1, 1, 1) - DateTime.Now,
            SerialNumberGrowthType.ByMonth => new DateTime(DateTime.Today.Year, DateTime.Today.Month, 1).AddMonths(1) - DateTime.Now,
            SerialNumberGrowthType.ByDay => DateTime.Today.AddDays(1) - DateTime.Now,
            SerialNumberGrowthType.ByWeek => TimeSpan.FromMilliseconds((long)TimeSpan.FromTicks(DateTime.Now.Ticks).TotalMilliseconds % (1000 * 60 * 60 * 24 * 7)),//1000 * 60 * 60 * 24 * 7
            SerialNumberGrowthType.ByHour => DateTime.Parse(DateTime.Now.ToString("yyyy-MM-dd HH:00:00")).AddHours(1) - DateTime.Now,
            SerialNumberGrowthType.ByMinute => DateTime.Parse(DateTime.Now.ToString("yyyy-MM-dd HH:mm:00")).AddMinutes(1) - DateTime.Now,
            _ => TimeSpan.FromMilliseconds(-1),
        };
        return await Cache.GetSerialNumberAsync("{SerialNumber}:" + key, quantity, expiration, cancellationToken);
    }
}
